package minidb.drive;
import java.io.IOException;
import java.util.*;

import minidb.buffer.Buffer;
import minidb.index.bTreeIndex;
import minidb.index.indexHeader;
import minidb.parse.exps.Condition;
import minidb.record.*;
import minidb.type.fieldinfo;
import static minidb.type.Const.*;

public class TableOp
{
	public void CreateTable(String tn,List<fieldinfo> fields, Condition con) throws FileOpException
	{
		TableInfo tab;
		Schema sch = new Schema();
		int pos = 0;
		for(int i = 0; i < fields.size(); i++){
			fieldinfo finfo = fields.get(i);
			finfo.position(pos);
			pos+=finfo.length();
			if(finfo.type()==TYPE.CHAR || finfo.type()==TYPE.STRING)
				pos++;
			sch.add(finfo);
		}
		tab = new TableInfo(sch, tn);
		if(con!=null){
			try {
				tab.addCondition(con);
			} catch (IOException e) {
				e.printStackTrace();
				throw new FileOpException(e.getMessage());
			}
		}
		tablePage.addTable(tab);
	}
	
	public Condition getCondition(String tn) throws FileOpException{
		TableInfo tab = tablePage.get(tn);
		if(tab==null){
			throw new FileOpException("NO SUCH TABLE: "+tn);
		}
		return tab.getCondition();
	}
	
	public void DropTable(String tn) throws FileOpException
	{
		TableInfo tab = tablePage.get(tn);
		if(tab == null)
			throw new FileOpException("NO SUCH TABLE: "+tn);
		while(true){
			synchronized(tab.lock){
				if(tab.ID < 0 || Thread.currentThread().getId() == tab.ID)
					break;
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		while(true){
			synchronized(tab.lock){
				if(tab.reading==0){
					Buffer buf = bufpool.pin(tab.startpage());
					int next = buf.getInt(NEXT_PAGE);
					dbFile.deallocPage(buf.pageNum());
					while(next!=0){
						bufpool.unpin(buf);
						buf = bufpool.pin(next);
						next = buf.getInt(NEXT_PAGE);
						dbFile.deallocPage(buf.pageNum());
					}
					bufpool.unpin(buf);
					break;
				}
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		RecordPage rec = new RecordPage(tab);
		bTreeIndex index = new bTreeIndex(tab, rec);
		Buffer buf = bufpool.pin(tab.indexPage());
		int next = buf.getInt(NEXT_PAGE);
		int next2;
		dbFile.deallocPage(buf.pageNum());
		while(next!=0){
			bufpool.unpin(buf);
			buf = bufpool.pin(next);
			next2 = buf.getInt(NEXT_PAGE);
			index.DeleteIndex(next);
			new indexHeader().deleteIndex(next);
			next = next2;
		}
		
		bufpool.unpin(buf);
		
		try {
			tablePage.deleteTable(tn);
		} catch (IOException e) {
			e.printStackTrace();
			throw new FileOpException(e.getMessage());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new FileOpException(e.getMessage());
		}		
		
		if(tab.checkPage()!=0){
			tab.deleteCondition();
		}

		index.close();
	}
}
